home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / lib / addr / ap_util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-11  |  12.4 KB  |  485 lines

  1. #include "util.h"
  2. #include "ap.h"
  3.  
  4. #if DEBUG > 1
  5. extern int debug;
  6. extern char *typtab[];
  7. #endif
  8.  
  9. /*  Standard routines for handling address list element nodes
  10.  
  11. /*  < 1978  B. Borden       Wrote initial version of parser code
  12.  *  78-80   D. Crocker      Reworked parser into current form
  13.  *  Apr 81  K. Harrenstein  Hacked for SRI
  14.  *  Jun 81  D. Crocker      Back in the fold.  Finished v7 conversion
  15.  *                          minor cleanups.
  16.  *                          repackaging into more complete set of calls
  17.  *  Jul 81  D. Crocker      ap_free & _alloc check for not 0 or -1
  18.  *                          malloc() error causes jump to ap_init error
  19.  */
  20.  
  21. struct ap_prevstruct   *ap_fle;   /* parse state top of stack           */
  22.                   /* "fl" => file, but could be other   */
  23.  
  24. int     (*ap_gfunc) ();           /* Ptr to character get fn            */
  25.  
  26. extern int      ap_peek;                  /* basic parse state info       */
  27. extern int    ap_perlev;
  28. extern int    ap_grplev;
  29.  
  30. extern char    *malloc();
  31.  
  32. /*  ********************  LIST NODE PRIMITIVES  *********************** */
  33.  
  34. AP_ptr
  35.     ap_alloc ()               /* create node, return pointer to it    */
  36. {
  37.     AP_ptr ap;
  38.  
  39.     /* NOSTRICT */
  40.     ap = (AP_ptr) malloc (sizeof (struct ap_node));
  41.     if (ap == (AP_ptr) 0)
  42.     return ((AP_ptr) 0);
  43.  
  44.     ap_ninit (ap);
  45.     return (ap);
  46. }
  47.  
  48. ap_ninit (ap)
  49.     register AP_ptr ap;
  50. {
  51.     ap -> ap_obtype = APV_NIL;
  52.     ap -> ap_obvalue = (char *) 0;
  53.     ap -> ap_ptrtype = APP_NIL;
  54.     ap -> ap_chain = (AP_ptr) 0;
  55. }
  56.  
  57. ap_free (ap)                      /* free node's storage                */
  58. register AP_ptr ap;
  59. {
  60.     switch ((int)ap)
  61.     {                             /* get rid of node, if have one       */
  62.     case OK:
  63.     case NOTOK:               /* nothing to free                    */
  64.         break;
  65.  
  66.     default:                  /* actually have a node               */
  67.         switch ((int)(ap -> ap_obvalue))
  68.         {                     /* get rid of its data string         */
  69.         case OK:
  70.         case NOTOK:       /* nothing to free                    */
  71.             break;
  72.  
  73.         default:
  74.             free (ap -> ap_obvalue);
  75.         }
  76.         free ((char *) ap);
  77.     }
  78. }
  79.  
  80. ap_fllnode (ap, obtype, obvalue)     /* add data to node at end of chain     */
  81. register AP_ptr ap;
  82. char   obtype;
  83. register char  *obvalue;
  84. {
  85.     extern char *strdup ();
  86.  
  87.     ap -> ap_obtype = obtype;
  88.     ap -> ap_obvalue = (obvalue == 0) ? (char *)0 : strdup (obvalue);
  89.  
  90. #if DEBUG > 1
  91.     if (debug)
  92.     printf ("(%s/'%s')", typtab[obtype], obvalue);
  93. #endif
  94. }
  95.  
  96. AP_ptr
  97.     ap_new (obtype, obvalue)  /* alloc & fill node                  */
  98. char    obtype;
  99. char   *obvalue;
  100. {
  101.     register AP_ptr nap;
  102.  
  103.     nap = ap_alloc ();
  104.     ap_fllnode (nap, obtype, obvalue);
  105.     return (nap);
  106. }
  107.  
  108. /*  ***************  LIST MANIPULATION PRIMITIVES  ******************* */
  109.  
  110. ap_insert (cur, ptrtype, new)     /* create/fill/insert node in list    */
  111. register AP_ptr cur;              /* where to insert after              */
  112. char ptrtype;                     /* inserted is more or new address    */
  113. register AP_ptr new;              /* where to insert after              */
  114. {
  115.  /* Now copy linkages from current node */
  116.  
  117.     new -> ap_ptrtype = cur -> ap_ptrtype;
  118.     new -> ap_chain = cur -> ap_chain;
  119.  
  120.  /* Now point current node at inserted node */
  121.  
  122.     cur -> ap_ptrtype = ptrtype;
  123.     cur -> ap_chain = new;
  124. }
  125.  
  126. AP_ptr
  127.     ap_sqinsert (cur, type, new)    /* insert sequence */
  128.     register AP_ptr cur,
  129.             new;
  130.     int type;
  131. {
  132.     AP_ptr oldptr;
  133.     int otype;
  134.  
  135.     switch ((int)new) {
  136.     case OK:
  137.     case NOTOK:
  138.         return ((AP_ptr) 0);
  139.     }
  140.  
  141.     oldptr = cur -> ap_chain;
  142.     otype = cur -> ap_ptrtype;
  143.     cur -> ap_chain = new;
  144.     cur -> ap_ptrtype = type;
  145.  
  146.     while (new -> ap_ptrtype != APP_NIL &&
  147.         new -> ap_chain != (AP_ptr) 0 &&
  148.         new -> ap_chain -> ap_obtype != APV_NIL)
  149.     new = new -> ap_chain;
  150.  
  151.     if (new -> ap_chain != (AP_ptr)0 && new -> ap_chain -> ap_obtype == APV_NIL)
  152.     ap_delete (new);
  153.  
  154.     new -> ap_chain = oldptr;
  155.     new -> ap_ptrtype = otype;
  156.     return (new);
  157. }
  158.  
  159. ap_delete (ap)                    /* remove next node in sequence       */
  160. register AP_ptr ap;
  161. {
  162.     register AP_ptr next;
  163.  
  164.     if (ap != (AP_ptr) 0 && ap -> ap_ptrtype != APP_NIL)
  165.     {                             /* only if there is something there   */
  166.     next = ap -> ap_chain;    /* link around one to be removed      */
  167.  
  168.     ap -> ap_ptrtype = next -> ap_ptrtype;
  169.     ap -> ap_chain = next -> ap_chain;
  170.  
  171.     ap_free (next);
  172.     }
  173. }
  174.  
  175. AP_ptr
  176.     ap_append (ap, obtype, obvalue)
  177.                   /* alloc, fill, insert node           */
  178. register AP_ptr ap;               /* node to insert after               */
  179. char    obtype;
  180. char   *obvalue;
  181. {
  182.     register AP_ptr nap;
  183.  
  184.     nap = ap_alloc ();
  185.     ap_fllnode (nap, obtype, obvalue);
  186.     ap_insert (ap, APP_ETC, nap);
  187.     return (nap);
  188. }
  189. /* */
  190.  
  191. AP_ptr
  192.        ap_add (ap, obtype, obvalue)
  193.                   /* try to append data to current node   */
  194. register AP_ptr ap;
  195. char    obtype;
  196. register char  *obvalue;
  197. {
  198.     extern char *multcat ();
  199.     register char  *ovalue;
  200.  
  201.     if (ap -> ap_obtype != obtype)
  202.     return (ap_append (ap, obtype, obvalue));
  203.     else                          /* same type or empty => can append     */
  204.     {
  205.     if (obvalue == 0)         /* No data to add                       */
  206.         return (OK);
  207.  
  208.     if ((ovalue = ap -> ap_obvalue) == (char *) 0)
  209.         ap_fllnode (ap, obtype, obvalue);
  210.     else                      /* add to existing data                 */
  211.     {
  212.         ovalue = ap -> ap_obvalue;
  213.         ap -> ap_obvalue = multcat (ovalue, " ", obvalue, (char *)0);
  214.         free (ovalue);
  215.     }
  216.  
  217. #if DEBUG > 1
  218.     if (debug)
  219.         printf ("+%d/'%s')", obtype, obvalue);
  220. #endif
  221.     }
  222.     return (OK);
  223. }
  224.  
  225. /* */
  226.  
  227. AP_ptr
  228.     ap_sqdelete (strt_node, end_node) /* remove nodes, through end node     */
  229. register AP_ptr strt_node;
  230. register AP_ptr end_node;
  231. {
  232.     switch ((int)strt_node) {
  233.     case OK:
  234.     case NOTOK:
  235.         return ((AP_ptr)0);
  236.     }
  237.     while (strt_node -> ap_ptrtype != APP_NIL) {
  238.     if (strt_node -> ap_chain == end_node) {
  239.                 /* last one requested                 */
  240.         ap_delete (strt_node);
  241.         return (strt_node -> ap_chain);
  242.     }
  243.     ap_delete (strt_node);
  244.     }
  245.     return ((AP_ptr) 0);          /* end of chain                       */
  246. }
  247.  
  248. AP_ptr
  249.     ap_1delete (ap)                   /* remove all nodes of address to NXT */
  250. register AP_ptr ap;               /* starting node                      */
  251. {
  252.     while (ap -> ap_ptrtype != APP_NIL) {
  253.     if (ap -> ap_ptrtype == APP_NXT)
  254.         return (ap -> ap_chain);
  255.     ap_delete (ap);
  256.     }
  257.     return ((AP_ptr) 0);                   /* end of chain              */
  258. }
  259.  
  260. ap_sqtfix (strt, end, obtype)     /* alter obtype of a node subsequence */
  261. register AP_ptr strt;
  262. register AP_ptr end;
  263. register char   obtype;
  264. {
  265.     for ( ; ; strt = strt -> ap_chain) {
  266.     if (strt -> ap_obtype != APV_CMNT)
  267.         strt -> ap_obtype = obtype;
  268.     if (strt == end || strt -> ap_ptrtype == APP_NIL)
  269.         break;
  270.     }
  271. }
  272.  
  273. /* */
  274.  
  275. AP_ptr
  276.     ap_move (to, from)  /* move node after from to be after to   */
  277.     register AP_ptr to,
  278.             from;
  279. {
  280.     register AP_ptr nodeptr;
  281.  
  282.     if (from -> ap_ptrtype == APP_NIL || from -> ap_chain == (AP_ptr) 0)
  283.     return (from);  /* quiet failure */
  284.  
  285.     nodeptr = from -> ap_chain;
  286.  
  287.     from -> ap_chain = nodeptr -> ap_chain;
  288.     from -> ap_ptrtype = nodeptr -> ap_ptrtype;
  289.  
  290.     ap_insert (to, APP_ETC, nodeptr);
  291.     return (from);      /* next in chain, now */
  292. }
  293.  
  294. AP_ptr
  295.     ap_sqmove (to, from, endtype)    /* move sequence */
  296.     register AP_ptr to,
  297.             from;
  298.     register char endtype;              /* copy only COMMENT and this */
  299. {
  300.     switch ((int)from) {
  301.     case OK:
  302.     case NOTOK:
  303.         return ((AP_ptr) 0);
  304.     }
  305.  
  306.     while (from -> ap_ptrtype != APP_NIL && from -> ap_chain != (AP_ptr) 0) {
  307.     if (endtype != (char) APV_NIL)
  308.         if (from -> ap_obtype != APV_CMNT && from -> ap_obtype != endtype)
  309.         break;
  310.     to = ap_move (to, from);
  311.     }
  312.  
  313.     return (to);          /* end of chain                       */
  314. }
  315.  
  316. /*  ************************  PARSE STATE  *************************** */
  317.  
  318. AP_ptr ap_pstrt,                  /* current last node in parse tree    */
  319.        ap_pcur;                   /* current last node in parse tree    */
  320.  
  321. ap_iinit (gfunc)                   /* input function initialization     */
  322. int     (*gfunc) ();
  323. {
  324.     ap_gfunc = gfunc;             /* Set character fetch func           */
  325.     ap_peek = -1;                 /* No lex peek char                   */
  326. }
  327.  
  328. ap_clear ()                     /* Clear out the parser state           */
  329. {
  330.     ap_grplev = 0;                 /* Zero group nesting depth          */
  331.     ap_perlev = 0;                 /* Zero <> nesting depth             */
  332. }
  333.  
  334. AP_ptr
  335.        ap_pinit (gfunc)           /* init, alloc & set start node       */
  336. int     (*gfunc) ();
  337. {
  338.     ap_iinit (gfunc);
  339.     return (ap_pstrt = ap_pcur = ap_alloc ());
  340. }
  341.  
  342. /*  parse state saving uses a linked list of state information,
  343.  *  recorded in ap_prevstruct structures.
  344.  *  the list is manipulated as a simple stack.
  345.  */
  346.  
  347. ap_ppush (gfunc)                  /* save parse context, ap_iinit    */
  348. int     (*gfunc) ();
  349. {
  350.     extern char *malloc ();
  351.     register struct ap_prevstruct  *tfil;
  352.  
  353.     /*NOSTRICT*/
  354.     if ((tfil = (struct ap_prevstruct *) malloc (sizeof (*tfil))) ==
  355.                 (struct ap_prevstruct *) NULL)
  356.     return (NOTOK);
  357.  
  358.     tfil -> ap_opeek = ap_peek;   /* save regular parse state info      */
  359.     tfil -> ap_ogroup = ap_grplev;
  360.     tfil -> ap_opersn = ap_perlev;
  361.     tfil -> ap_prvgfunc = ap_gfunc;
  362.     tfil -> ap_prvptr = ap_fle;   /* save previous stack entry          */
  363.     ap_fle = tfil;                /* save current stack entry           */
  364.     ap_iinit (gfunc);             /* create new parse state             */
  365.     return (OK);
  366. }
  367.  
  368. ap_ppop ()                        /* restore previous parse state       */
  369. {
  370.     register struct ap_prevstruct  *tfil;
  371.  
  372.     tfil = ap_fle;
  373.     ap_peek = tfil -> ap_opeek;
  374.     ap_grplev = tfil -> ap_ogroup;
  375.     ap_perlev = tfil -> ap_opersn;
  376.     ap_gfunc = tfil -> ap_prvgfunc;
  377.     ap_fle = tfil -> ap_prvptr;
  378.     free ((char *) tfil);
  379. }
  380. /* */
  381.  
  382. /*  the next three routines handle most of the overhead for acquiring
  383.  *  the address list from a file.
  384.  */
  385.  
  386. ap_flget ()                      /* get character from included file   */
  387. {
  388.     register int c;
  389.  
  390.     c = getc (ap_fle -> ap_curfp);
  391.  
  392.     if (c == '\n')
  393.     return (',');           /* a minor convenience */
  394.  
  395.     return (c);
  396. }
  397.  
  398. ap_fpush (file)                  /* indirect input from file           */
  399. char   file[];
  400. {
  401.     if (ap_ppush (ap_flget) == NOTOK)   /* save current & set for file input */
  402.     return (NOTOK);
  403.  
  404.     if ((ap_fle -> ap_curfp = fopen (file, "r")) == (FILE *) NULL)
  405.     {                             /* couldn't get the file, tho         */
  406.     ap_ppop ();
  407.     return (NOTOK);
  408.     }
  409.     return (OK);
  410. }
  411.  
  412. ap_fpop ()                       /* pop the stack, if any input nested */
  413. {
  414.     if (ap_fle -> ap_curfp != NULL)
  415.     fclose (ap_fle -> ap_curfp);
  416.  
  417.     ap_ppop ();
  418. }
  419.  
  420. /*  ******************  PARSE LIST MANIPULATION  ********************* */
  421.  
  422. /*  these echo the basic list manipuation primitives, but use ap_pcur
  423.  *  for the pointer and any insert will cause ap_pcur to be updated
  424.  *  to point to the new node.
  425.  */
  426.  
  427. ap_palloc ()                      /* alloc, insert after pcur           */
  428. {
  429.     ap_pnsrt (ap_alloc (), APP_ETC);
  430. }
  431.  
  432. ap_pfill (obtype, obvalue)        /* add data to node at end of chain     */
  433. char   obtype;
  434. register char  *obvalue;
  435. {
  436.     extern char *strdup ();
  437.  
  438.     ap_pcur -> ap_obtype = obtype;
  439.     ap_pcur -> ap_obvalue =
  440.         (obvalue == (char *) 0) ? (char *) 0 : strdup (obvalue);
  441. #if DEBUG > 1
  442.     if (debug)
  443.     printf ("(%s/'%s')", typtab[obtype], obvalue);
  444. #endif
  445. }
  446.  
  447. ap_pnsrt (ap, ptrtype)          /* add node to end of parse chain     */
  448. register AP_ptr ap;
  449. char    ptrtype;
  450. {
  451.     register AP_ptr rap_pcur;
  452.  
  453.     if ((rap_pcur = ap_pcur) -> ap_obtype == APV_NIL)
  454.     {                             /* current one can be used            */
  455.     rap_pcur -> ap_obtype = ap -> ap_obtype;
  456.     rap_pcur -> ap_obvalue = ap -> ap_obvalue;
  457.     ap -> ap_obvalue = 0;
  458.     ap_free (ap);
  459.     } else {                      /* really do the insert               */
  460.     rap_pcur -> ap_ptrtype = ptrtype;
  461.     rap_pcur -> ap_chain = ap;
  462.     ap_pcur = ap;
  463.     }
  464. }
  465.  
  466. ap_pappend (obtype, obvalue)      /* alloc, fill, append at end         */
  467. char    obtype;
  468. char   *obvalue;
  469. {
  470.     ap_palloc ();                 /* will update pcur                   */
  471.     ap_fllnode (ap_pcur, obtype, obvalue);
  472. }
  473.  
  474. ap_padd (obtype, obvalue)         /* try to append data to current node */
  475. char    obtype;
  476. char  *obvalue;
  477. {
  478.     register AP_ptr nap;
  479.  
  480.     nap = ap_add (ap_pcur, obtype, obvalue);
  481.  
  482.     if (nap != OK)                /* created new node                   */
  483.     ap_pcur = nap;
  484. }
  485.